package supermemo.input;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;

import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

/**
 * @version 1.00 1999-07-17
 * @author Cay Horstmann
 */

public class SortFilterModel extends AbstractTableModel
{
	private static final long serialVersionUID = -8053592706353069765L;

	public SortFilterModel(TableModel m) 
	{
		model = m;
		rows = new Row[model.getRowCount()];
		for (int i = 0; i < rows.length; i++) {
			rows[i] = new Row();
			rows[i].index = i;
		}
	}

	public void sort(int c) {
		sortColumn = c;
		Arrays.sort(rows);
		fireTableDataChanged();
	}

	public void addMouseListener(final JTable table) {
		table.getTableHeader().addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent event) { // check for double
				// click
				if (event.getClickCount() < 2)
					return;

				// find column of click and
				int tableColumn = table.columnAtPoint(event.getPoint());

				// translate to table model index and sort
				int modelColumn = table.convertColumnIndexToModel(tableColumn);
				sort(modelColumn);
			}
		});
	}

	/*
	 * compute the moved row for the three methods that access model elements
	 */

	public Object getValueAt(int r, int c) 
	{
		if(rows.length > 0)
		{
			return model.getValueAt(rows[r].index, c);
		}else
		{
			return 0; //???
		}
	}

	public boolean isCellEditable(int r, int c) 
	{
		if(rows.length > 0)
		{
			return model.isCellEditable(rows[r].index, c);
		}else
		{
			return false;
		}
	}

	public void setValueAt(Object aValue, int r, int c) 
	{
		if(rows.length > 0)
		{
			model.setValueAt(aValue, rows[r].index, c);
		}
	}

	/*
	 * delegate all remaining methods to the model
	 */

	public int getRowCount() {
		return model.getRowCount();
	}

	public int getColumnCount() {
		return model.getColumnCount();
	}

	public String getColumnName(int c) {
		return model.getColumnName(c);
	}

	public Class getColumnClass(int c) {
		return model.getColumnClass(c);
	}

	/*
	 * this inner class holds the index of the model row Rows are compared by
	 * looking at the model row entries in the sort column
	 */

	private class Row implements Comparable 
	{
		public int index;

		public int compareTo(Object other) {
			Row otherRow = (Row) other;
			Object a = model.getValueAt(index, sortColumn);
			Object b = model.getValueAt(otherRow.index, sortColumn);
			if (a instanceof Comparable)
				return ((Comparable) a).compareTo(b);
			else
				return index - otherRow.index;
		}
	}

	private TableModel model;

	private int sortColumn;

	private Row[] rows;
}